package de.tum.in.eist.im.server.Chat;

import java.util.ArrayList;
import java.util.List;

import de.tum.in.eist.im.client.Chat.ChatChannel.ChatMessageHandlerService;
import de.tum.in.eist.im.server.Datastore.DatastoreManager;
import de.tum.in.eist.im.shared.ChatChannel.ChatChannel;
import de.tum.in.eist.im.shared.Message.Message;
import de.tum.in.eist.im.shared.User.User;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class ChatMessageHandlerServiceImpl extends RemoteServiceServlet implements
		ChatMessageHandlerService {
	
	/**
	 * returns an array of all message of a specific channel
	 * @param chatChannelId the id the client wants the old messages
	 * @return an array of all messages of the specific channel
	 */
	@Override
	public Message[] getMessagesFromDatabase(Long chatChannelId) {
		DatastoreManager datastore = new DatastoreManager();
		return datastore.getMessagesFromDatabase(chatChannelId);
	}
	
	/**
	 * change the instance variable message of this class and notify the monitor object to finish the push method
	 * @param message the message which should become the new instance variable
	 * @return true
	 */
	public Boolean sendMessage (Message message) {
		
		// save message in datastore
		DatastoreManager datastore = new DatastoreManager();
		datastore.sendMessageToServer(message);
		
		// push the message to the user in the channel
		ChannelService channelService = ChannelServiceFactory.getChannelService();
		String result = "{{\"type\":\"1\"}, {\"messageText\":\"" + message.getMessageText() + "\"}, {\"messageUser\":\"" + message.getMessageUser().getUsername() + "\"}, {\"messageDate\":\"" + message.getMessageDate().toString() + "\"}, {\"messageChatID\":\"" + message.getMessageChatId().longValue() + "\"}}";	
		
		// select user in channel to deliver the message
		ChatChannel theChatChannel = null;
		if (ChatPanelServiceImpl.getOpenChannels() != null || ChatPanelServiceImpl.getOpenPrivateChannels() != null) {
			for (ChatChannel chatChannel : ChatPanelServiceImpl.getOpenChannels()) {
				if(chatChannel.getChatId().equals(message.getMessageChatId())) {
					theChatChannel = chatChannel;
					break;
				}
			}
			for (ChatChannel chatChannel : ChatPanelServiceImpl.getOpenPrivateChannels()) {
				if(chatChannel.getChatId().equals(message.getMessageChatId())) {
					theChatChannel = chatChannel;
					break;
				}
			}
		}
		
		if (theChatChannel != null) {
			for (User u : theChatChannel.getUserInChannel()) {
				channelService.sendMessage(new ChannelMessage(u.getUsername(), result));
			}
		}
		
		return Boolean.TRUE;
	}
	
	/**
	 * add a user as online to the list of the current! channel
	 * @param user the user to add to the list of online user
	 * @return true
	 */
	@Override
	public Boolean addUserAsOnline (User user, Long chatChannelId) {

		System.out.println("this chat id " + chatChannelId);
		// get chat channel
		ChatChannel theChatChannel = null;
		for (ChatChannel openChatChannel : ChatPanelServiceImpl.getOpenChannels()) {
			System.out.println("openchat:" + openChatChannel.getChatId());
			if (openChatChannel.getChatId().equals(chatChannelId)) {
				theChatChannel = openChatChannel;
				break;
			}
		}
		
		// add user to the chat channel
		if (null != theChatChannel)
			theChatChannel.addUserToChatChannel(user);
		else 
			System.out.println("server POnline method!!");
		
		return true;
	}

	public Boolean addUserAsOnlineToPrivate (User user, Long chatChannelId) {
		System.out.println("this chat id " + chatChannelId);
		// get chat channel
		ChatChannel theChatChannel = null;
		for (ChatChannel openChatChannel : ChatPanelServiceImpl.getOpenPrivateChannels()) {
			System.out.println("openchat:" + openChatChannel.getChatId());
			if (openChatChannel.getChatId().equals(chatChannelId)) {
				theChatChannel = openChatChannel;
				break;
			}
		}
		
		// add user to the chat channel
		if (null != theChatChannel)
			theChatChannel.addUserToChatChannel(user);
		else 
			System.out.println("server POnline method!!");
		
		return true;
	}
	
	/**
	 * remove a user from the list of the current! channel
	 * @param user to add to the list of online user
	 * @return true
	 */
	@Override
	public Boolean removeUserAsOnline (User user, Long chatChannelId) {
		// get chat channel
		/*
		ChatChannel theChatChannel = null;
		for (ChatChannel openChatChannel : ChatPanelServiceImpl.getOpenChannels()) {
			if (openChatChannel.getChatId().equals(chatChannelId)) {
				theChatChannel = openChatChannel;
				break;
			}
		}*/
		// TODO: !!!
		// add user to the chat channel
		//theChatChannel.removeUserFromChatChannel(user);
		 // write!!!
		return true;
	}
	
	/**
	 * returns a list of online user of the current! channel
	 * @param chatChannelId the id of the chat channel
	 * @return List of User in the current channel
	 */
	@Override
	public List<User> getOnlineUsersFromServer(Long chatChannelId) {
		ChatChannel theChatChannel = null;
		for (ChatChannel openChatChannel : ChatPanelServiceImpl.getOpenChannels()) {
			if (openChatChannel.getChatId().equals(chatChannelId)) {
				theChatChannel = openChatChannel;
				break;
			}
		}
		if (null == theChatChannel) {
			List<User> emptyList = new ArrayList<User>();
			return emptyList;
		} else {
			return theChatChannel.getUserInChannel();
		}
	}
}
